package com.shopping.mall.core.util;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shopping.mall.base.redis.RedisHeader;
import com.shopping.mall.core.module.freemarkerMail.entity.FreemarkerMail;
import com.shopping.mall.core.module.freemarkerMail.entity.MailType;
import com.shopping.mall.core.module.freemarkerMail.mapper.FreemarkerMailMapper;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.io.StringWriter;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 邮件工具类
 *
 * @Author ZZY
 * @Date 2021/7/27
 */
@Component
@Setter
@Slf4j
public class MailUtils {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private JavaMailSender mailSender;
    @Autowired
    private FreemarkerMailMapper freemarkerMailMapper;

    @Value("${spring.mail.username}")
    private String from = "15613469426@163.com"; //邮件发送人地址

    @Value("${spring.mail.nickname}")
    private final String nickname = "shopping"; //邮件发送人名称

    /**
     * 解析模板
     * @param configuration
     * @param templateName
     * @param templateValue
     * @param orderNumber
     * @param timestamp
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    public String processTemplate(Configuration configuration, String templateName, String templateValue,String authCode, String orderNumber, Timestamp timestamp) throws IOException, TemplateException {
        Map<String, Object> root = new HashMap<>(4);
        root.put("authCode", authCode);
        if (timestamp!=null){
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            final Date date = new Date(timestamp.getTime());
            final String time = df.format(date);
            root.put("time",time);
        }else {
            root.put("time",null);
        }
        root.put("orderNumber", orderNumber);

        StringWriter stringWriter = new StringWriter();
        Template template = new Template(templateName, templateValue, configuration);
        template.process(root, stringWriter);
        return stringWriter.toString();
    }

    /**
     * 配置 freemarker configuration
     *
     * @return
     */
    public Configuration configuration() {
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_27);
        StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
        configuration.setTemplateLoader(stringTemplateLoader);
        configuration.setDefaultEncoding("UTF-8");
        return configuration;
    }


    /**
     * 发送注册邮件
     *
     * @param mailToAddress : 邮件接收地址
     */
    @Async
    public void sendRegisterMail(String mailToAddress) {
        try {
            String templateName = "hello-template";
            final String templateValue = freemarkerMailMapper.getLastTemplate(MailType.sendRegisterMail.getType()).getTemplate();
            Configuration configuration = configuration();
            String authCode = (int) ((Math.random() * 9 + 1) * 100000) + "";
            final String text = processTemplate(configuration, templateName, templateValue,authCode,null,null);

            //存储30分钟
            redisTemplate.opsForValue().set(RedisHeader.MAIL_REGISTER_CODE.getHeader() + mailToAddress, authCode, 60 * 30L, TimeUnit.SECONDS);
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
            messageHelper.setFrom(nickname + "<" + from + ">");
            messageHelper.setTo(mailToAddress);
            messageHelper.setSubject("register mail");
//            messageHelper.setText("<div><h3>尊敬的用户您好,</h3><hr><br>您本次注册的验证码是:<br><h1 style=\"font-family: 方正粗黑宋简体,serif\">" + authCode + "</h1>30分钟内有效,如非本人操作,请忽略此邮件</div>\n", true);//邮件内容
            messageHelper.setText(text,true);
            mailSender.send(messageHelper.getMimeMessage());
            log.info("验证码发送成功");
        } catch (Exception e) {
            log.error("验证码发送失败:{}",e.getStackTrace());
        }
    }

    /**
     * 发送忘记密码邮件
     *
     * @param mailToAddress : 邮件接收地址
     */
    @Async
    public void sendForgetMail(String mailToAddress) {
        try {
            String templateName = "hello-template";
            final String templateValue = freemarkerMailMapper.getLastTemplate(MailType.sendForgetMail.getType()).getTemplate();
            Configuration configuration = configuration();
            String authCode = (int) ((Math.random() * 9 + 1) * 100000) + "";
            final String text = processTemplate(configuration, templateName, templateValue,authCode,null,null);

            //存储30分钟
            redisTemplate.opsForValue().set(RedisHeader.FORGET_PASSWORD_CODE.getHeader() + mailToAddress, authCode, 60 * 30L, TimeUnit.SECONDS);
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
            messageHelper.setFrom(nickname + "<" + from + ">");
            messageHelper.setTo(mailToAddress);
            messageHelper.setSubject("forget password mail");
//            messageHelper.setText("<div><h3>注意!您正在重置密码!</h3><hr><br>您本次用于重置密码的验证码是:<br><h1 style=\"font-family: 方正粗黑宋简体,serif\">" + authCode + "</h1>30分钟内有效,请注意账号安全</div>\n", true);//邮件内容
            messageHelper.setText(text,true);
            mailSender.send(messageHelper.getMimeMessage());
            log.info("验证码发送成功");
        } catch (Exception e) {
            log.error("验证码发送失败:{}",e.getStackTrace());
        }
    }

    /**
     * 换绑时解除绑定
     *
     * @param mailToAddress: 邮件接收地址
     */
    @Async
    public void sendUnbindMail(String mailToAddress) {
        try {
            String templateName = "hello-template";
            final String templateValue = freemarkerMailMapper.getLastTemplate(MailType.sendUnbindMail.getType()).getTemplate();
            Configuration configuration = configuration();
            String authCode = (int) ((Math.random() * 9 + 1) * 100000) + "";
            final String text = processTemplate(configuration, templateName, templateValue,authCode,null,null);

            //存储30分钟
            redisTemplate.opsForValue().set(RedisHeader.MAIL_UNBIND_CODE.getHeader() + mailToAddress, authCode, 60 * 30L, TimeUnit.SECONDS);
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
            messageHelper.setFrom(nickname + "<" + from + ">");
            messageHelper.setTo(mailToAddress);
            messageHelper.setSubject("unbind mail");
//            messageHelper.setText("<div><h3>注意!您正在解除绑定!</h3><hr><br>您本次用于解除邮箱绑定的验证码是:<br><h1 style=\"font-family: 方正粗黑宋简体,serif\">" + authCode + "</h1>30分钟内有效,请注意账号安全</div>\n", true);//邮件内容
            messageHelper.setText(text,true);
            mailSender.send(messageHelper.getMimeMessage());
            log.info("验证码发送成功");
        } catch (Exception e) {
            log.error("验证码发送失败:{}",e.getStackTrace());
        }
    }

    /**
     * 绑定新邮箱
     *
     * @param mailToAddress: 邮件接收地址
     */
    @Async
    public void sendBindMail(String mailToAddress) {
        try {
            String templateName = "hello-template";
            final String templateValue = freemarkerMailMapper.getLastTemplate(MailType.sendBindMail.getType()).getTemplate();
            Configuration configuration = configuration();
            String authCode = (int) ((Math.random() * 9 + 1) * 100000) + "";
            final String text = processTemplate(configuration, templateName, templateValue,authCode,null,null);

            //存储30分钟
            redisTemplate.opsForValue().set(RedisHeader.MAIL_BIND_CODE.getHeader() + mailToAddress, authCode, 60 * 30L, TimeUnit.SECONDS);
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
            messageHelper.setFrom(nickname + "<" + from + ">");
            messageHelper.setTo(mailToAddress);
            messageHelper.setSubject("change bindMail");
//            messageHelper.setText("<div><h3>注意!您正在绑定邮箱!</h3><hr><br>您本次用于邮箱绑定的验证码是:<br><h1 style=\"font-family: 方正粗黑宋简体,serif\">" + authCode + "</h1>30分钟内有效,如非本人操作,请忽略此邮件</div>\n", true);//邮件内容
            messageHelper.setText(text,true);
            mailSender.send(messageHelper.getMimeMessage());
            log.info("验证码发送成功");
        } catch (Exception e) {
            log.error("验证码发送失败:{}",e.getStackTrace());
        }
    }

    /**
     * 发送已支付邮件
     *
     * @param mailToAddress: 邮件接收地址
     */
    public void sendPayedMail(String mailToAddress, String orderNumber, Timestamp timestamp) {
        try {
            System.out.println("支付邮件");
            String templateName = "hello-template";
            final String templateValue = freemarkerMailMapper.getLastTemplate(MailType.sendPayedMail.getType()).getTemplate();
            System.out.println(templateName);
            Configuration configuration = configuration();
            final String text = processTemplate(configuration, templateName, templateValue,null,orderNumber,timestamp);
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
            messageHelper.setFrom(nickname + "<" + from + ">");
            messageHelper.setTo(mailToAddress);
            messageHelper.setSubject("have paid");
//            messageHelper.setText("<div></h1>Your order no. "+orderNumber+" has been paid successfully at "+df.format(date)+", please pay attention to the order information, thank you for your patronage.</div>\n", true);//邮件内容
            messageHelper.setText(text,true);
            mailSender.send(messageHelper.getMimeMessage());
            log.info("验证码发送成功");
        } catch (Exception e) {
            log.error("验证码发送失败:{}",e.getStackTrace());
        }
    }

    /**
     * 发送已发货邮件
     *
     * @param mailToAddress: 邮件接收地址
     */
    public void sendDeliverMail(String mailToAddress, String orderNumber, Timestamp timestamp) {
        try {
            String templateName = "hello-template";
            final String templateValue = freemarkerMailMapper.getLastTemplate(MailType.sendDeliverMail.getType()).getTemplate();
            Configuration configuration = configuration();
            final String text = processTemplate(configuration, templateName, templateValue,null,orderNumber,timestamp);

            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
            messageHelper.setFrom(nickname + "<" + from + ">");
            messageHelper.setTo(mailToAddress);
            messageHelper.setSubject("have delivered");
//            messageHelper.setText("<div></h1>Your order no. "+orderNumber+" has been successfully shipped at "+df.format(date)+", please pay attention to the order information, thank you for your patronage.</div>\n", true);//邮件内容
            messageHelper.setText(text);
            mailSender.send(messageHelper.getMimeMessage());
            log.info("验证码发送成功");
        } catch (Exception e) {
            log.error("验证码发送失败:{}",e.getStackTrace());
        }
    }

    /**
     * 已发货超过30天自动完成
     * @param mailToAddress
     * @param orderNumber
     * @param timestamp
     */
    public void send30DayMail(String mailToAddress, String orderNumber, Timestamp timestamp){
        try {
            String templateName = "hello-template";
            final String templateValue = freemarkerMailMapper.getLastTemplate(MailType.send30DayMail.getType()).getTemplate();
            Configuration configuration = configuration();
            final String text = processTemplate(configuration, templateName, templateValue,null,orderNumber,timestamp);

            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
            messageHelper.setFrom(nickname + "<" + from + ">");
            messageHelper.setTo(mailToAddress);
            messageHelper.setSubject("delivered 30 days");
            messageHelper.setText(text);
            mailSender.send(messageHelper.getMimeMessage());
            log.info("验证码发送成功");
        } catch (Exception e) {
            log.error("验证码发送失败:{}",e.getStackTrace());
        }
    }

    /**
     * 用户点击完成
     * @param mailToAddress
     * @param orderNumber
     * @param timestamp
     */
    public void sendClickMail(String mailToAddress, String orderNumber, Timestamp timestamp){
        try {
            String templateName = "hello-template";
            final String templateValue = freemarkerMailMapper.getLastTemplate(MailType.sendClickMail.getType()).getTemplate();
            Configuration configuration = configuration();
            final String text = processTemplate(configuration, templateName, templateValue,null,orderNumber,timestamp);

            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
            messageHelper.setFrom(nickname + "<" + from + ">");
            messageHelper.setTo(mailToAddress);
            messageHelper.setSubject("已发货超过30天");
            messageHelper.setText(text);
            mailSender.send(messageHelper.getMimeMessage());
            log.info("验证码发送成功");
        } catch (Exception e) {
            log.error("验证码发送失败:{}",e.getStackTrace());
        }
    }
}
